﻿using Maba3ref.Yammer.User;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Maba3ref.Yammer
{
    /// <summary>
    /// Group of methods to wrap Yammer APIs
    /// </summary>
    public class YammerAPI
    {
        #region Private Members

        /// <summary>
        /// URLs of all messages actions
        /// </summary>
        private static string[] jsonUrls = { "https://www.yammer.com/api/v1/messages.json", 
                                              "https://www.yammer.com/api/v1/messages/my_feed.json",
                                              "https://www.yammer.com/api/v1/messages/algo.json",
                                              "https://www.yammer.com/api/v1/messages/following.json",
                                              "https://www.yammer.com/api/v1/messages/sent.json",
                                              "https://www.yammer.com/api/v1/messages/private.json",
                                              "https://www.yammer.com/api/v1/messages/received.json"};

        #endregion Private Members

        #region Public Members

        /// <summary>
        /// Message actions enumeration type
        /// </summary>
        public enum MessageActions : ushort
        {
            /// <summary>
            /// All public messages in the user’s (whose access token is being used to make the API call henceforth referred to as current user) Yammer network. Corresponds to “All” conversations in the Yammer web interface.
            /// </summary>
            Messages = 0,
            
            /// <summary>
            /// The user’s feed, based on the selection they have made between “Following” and “Top” conversations.
            /// </summary>
            MyFeed = 1,

            /// <summary>
            /// The algorithmic feed for the user that corresponds to “Top” conversations, which is what the vast majority of users will see in the Yammer web interface.
            /// </summary>
            Algo = 2,

            /// <summary>
            /// The “Following” feed which is conversations involving people, groups and topics that the user is following.
            /// </summary>
            Following = 3,

            /// <summary>
            /// All messages sent by the user. Alias for /api/v1/messages/from_user/logged-in_user_id.format.
            /// </summary>
            Sent = 4,

            /// <summary>
            /// Private messages received by the user.
            /// </summary>
            Private = 5,

            /// <summary>
            /// All messages received by the user.
            /// </summary>
            Received = 6
        };

        #endregion Public Members

        #region Public Methods

        /// <summary>
        /// 01 - Generat URL for https://www.yammer.com/dialog/oauth?client_id=
        /// </summary>
        /// <param name="client_id">Client ID</param>
        /// <param name="redirect_url">Redirect URL</param>
        /// <returns>Formatted URL to request authentication code</returns>
        public static string GenerateOAuthWithClientID(string client_id, string redirect_url)
        {
            return string.Format("https://www.yammer.com/dialog/oauth?client_id={0}&redirect_uri={1}", client_id, redirect_url);
        }

        /// <summary>
        /// 02 - Fetch access token for a user
        /// </summary>
        /// <param name="client_id">Client ID</param>
        /// <param name="client_secret">Client Secret</param>
        /// <param name="code">Code string</param>
        /// <returns>Instance of UserAccessToken or null</returns>
        public static UserAccessToken FetchAccessToken(string client_id, string client_secret, string code)
        {
            string accessToenURL = GenerateAccessTokenURL(client_id, client_secret, code);

            RestClient rest = new RestClient(accessToenURL);
            RestRequest request = new RestRequest(Method.GET);

            IRestResponse<UserAccessToken> response = rest.Execute<UserAccessToken>(request);
            return response.Data;
        }

        #endregion Public Methods

        #region Public Messages Methods

        /// <summary>
        /// All public messages in the user’s (whose access token is being used to make the API call henceforth referred to as current user) Yammer network. Corresponds to “All” conversations in the Yammer web interface.
        /// </summary>
        /// <param name="access_token">User access token</param>
        /// <param name="older_than">Returns messages older than the message ID specified as a numeric string. This is useful for paginating messages. For example, if you’re currently viewing 20 messages and the oldest is number 2912, you could append “?older_than=2912″ to your request to get the 20 messages prior to those you’re seeing.</param>
        /// <param name="newer_than">Returns messages newer than the message ID specified as a numeric string. This should be used when polling for new messages. If you’re looking at messages, and the most recent message returned is 3516, you can make a request with the parameter “?newer_than=3516″ to ensure that you do not get duplicate copies of messages already on your page.</param>
        /// <param name="limit">Max items number you want to retrieve from Yammer</param>
        /// <param name="action">Value from MessageActions type</param>
        /// <param name="threaded">threaded=true will only return the first message in each thread. This parameter is intended for apps which display message threads collapsed. threaded=extended will return the thread starter messages in order of most recently active as well as the two most recent messages, as they are viewed in the default view on the Yammer web interface.</param>
        /// <remarks>If older_than is empty then newer_than it will be used otherwise older_than will be used</remarks>
        /// <returns>Instance of YammerMessage</returns>
        public static YammerMessageCollection GetMessages(string access_token, string older_than, string newer_than, ushort limit, MessageActions action, string threaded = "true")
        {
            string than = string.Empty;

            // if not empty then use it
            if (!String.IsNullOrEmpty(older_than))
            {
                than = String.Format("older_than={0}", older_than);
            }
            else if (!String.IsNullOrEmpty(newer_than))
            {
                than = String.Format("newer_than={0}", newer_than);
            }

            // check threaded value, it must be either true or extended
            if (threaded != "true" || threaded != "extended")
                threaded = "true";

            string url = string.Format("{0}?access_token={1}&limit={2}&{3}", jsonUrls[(ushort)action], access_token, limit, than);
            RestClient rest = new RestClient(url);

            RestRequest request = new RestRequest(Method.GET);

            // automatically deserialize result
            // return content type is sniffed but can be explicitly set via RestClient.AddHandler();
            IRestResponse<YammerMessageCollection> response = rest.Execute<YammerMessageCollection>(request);
            return response.Data;
        }

        #endregion Public Messages Methods

        #region Public Users Methods

        /// <summary>
        /// Get user data
        /// </summary>
        /// <param name="access_token">User access token</param>
        /// <param name="user_id">User ID</param>
        /// <returns>Instance of YammerUserInfo or null</returns>
        public static YammerUserInfo GetUser(string access_token, string user_id)
        {
            string url = String.Format("https://www.yammer.com/api/v1/users/{0}.json?access_token={1}", user_id, access_token);

            RestClient rest = new RestClient(url);

            RestRequest request = new RestRequest(Method.GET);

            // automatically deserialize result
            // return content type is sniffed but can be explicitly set via RestClient.AddHandler();
            IRestResponse<YammerUserInfo> response = rest.Execute<YammerUserInfo>(request);
            return response.Data;
        }

        #endregion Public Users Methods

        #region Private Methods

        /// <summary>
        /// Generate URL for https://www.yammer.com/oauth2/access_token.json?client_id={0}&client_secret={1}&code={2}
        /// </summary>
        /// <param name="client_id">Client ID</param>
        /// <param name="client_secret">Client Secret</param>
        /// <param name="code">Code string</param>
        /// <returns>Formatted URL to request access token code</returns>
        private static string GenerateAccessTokenURL(string client_id, string client_secret, string code)
        {
            return string.Format("https://www.yammer.com/oauth2/access_token.json?client_id={0}&client_secret={1}&code={2}", client_id, client_secret, code);
        }

        #endregion Private Methods
    }
}
